package com.zm.demo.shoppingmall.gateway.controller;

import com.zm.demo.shoppingmall.common.util.OKHttpUtil;
import com.zm.demo.shoppingmall.gateway.service.UserManager;
import com.zm.demo.shoppingmall.user.model.TUser;
import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.apm.toolkit.trace.CallableWrapper;
import org.apache.skywalking.apm.toolkit.trace.Tag;
import org.apache.skywalking.apm.toolkit.trace.Trace;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.*;
import java.util.stream.Collectors;

/**
 * @desc:
 * @author: z01140
 * @date: 2021/5/24 17:08
 */
@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserManager userManager;


    @GetMapping("/getUserByMobilephone")
    public TUser getUserByMobilephone(String mobilephone){
        return userManager.getUserByMobilePhone(mobilephone);
    }

    @Tag(key = "userId", value = "arg[0]")
    @GetMapping("/getUserById")
    public TUser getUserById(Integer userId) throws Exception{

        traceTest(Arrays.asList(1,2));
        traceTest1(Arrays.asList(2,1));

        log.info("/user/getUserById，参数：userId={}", userId);
        TUser user = userManager.getUserById(userId);
        log.info("/user/getUserById，结果={}", user.toString());
        return user;
    }


    @Tag(key = "userId", value = "arg[0]")
    @GetMapping("/getUserByIdMulti")
    public List<TUser> getUserByIdMuilti(Integer userId) throws Exception{
        ExecutorService executorService = Executors.newFixedThreadPool(10);

        traceTest(Arrays.asList(1,2));
        traceTest1(Arrays.asList(2,1));

        List<Callable<TUser>> list = new ArrayList<>();
        List<TUser> tUsers = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            Callable<TUser> callable = ()->{
                log.info("/user/getUserByIdMulti，参数：userId={}", userId);
                TUser user = userManager.getUserById(userId);
                log.info("/user/getUserByIdMulti，结果={}", user.toString());
                return user;
//                OKHttpUtil.get("http://www.baidu.com");
//                return null;
            };
            list.add(callable);
        }
        List<Future<TUser>> futures = executorService.invokeAll(list);
        executorService.shutdown();
        return futures.stream().map( f -> {
            try {
                return f.get();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
            return null;
        }).collect(Collectors.toList());
    }

    @Tag(key = "userId", value = "arg[0]")
    @GetMapping("/getUserByIdMultiSky")
    public List<TUser> getUserByIdMultiSky(Integer userId) throws Exception{
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        traceTest(Arrays.asList(1,2));
        traceTest1(Arrays.asList(2,1));
        List<CallableWrapper<TUser>> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            CallableWrapper<TUser> callable = CallableWrapper.of(()->{
                log.info("/user/getUserByIdMultiSky，参数：userId={}", userId);
                TUser user = userManager.getUserById(userId);
                log.info("/user/getUserByIdMultiSky，结果={}", user.toString());

                return user;
            });
            list.add(callable);
        }
        //多线程使用翻车现场，线程池调用以后又使用callable.call()单线程调用一次
        List<Future<TUser>> futures = executorService.invokeAll(list);
        executorService.shutdown();
        return futures.stream().map( f -> {
            try {
                return f.get();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
            return null;
        }).collect(Collectors.toList());
    }


    @PostMapping("/addUser")
    public int addUser(@RequestBody TUser user){
        return userManager.addUser(user);
    }

    private void traceTest(List<Integer> integers){
        log.info("no trace");
    }

    @Trace
    @Tag(key = "param[1]", value = "arg[0].[0]")
    private void traceTest1(List<Integer> integers){
        log.info("trace..");
    }
}
